package com.abbas.smartCity.okhttp

import android.os.Handler
import com.abbas.smartCity.App
import com.abbas.smartCity.util.toRequestBody
import com.google.gson.Gson
import okhttp3.*
import java.io.IOException

/**
 * 听到要学Retrofit（或者听到 ‘学’）就感觉要世界崩塌
 * 那我们就以最低限度编码
 * 学什么新东西？okhttp也很强的好不好
 * 什么？你不会kotlin？那我不带你玩了
 *
 * kotlin支持特性关键字object实现 全局单例
 */
object KOkGo {

    private val okHttpClient: OkHttpClient = OkHttpClient.Builder()
        .addInterceptor { chain ->//在此处拦截
            return@addInterceptor chain.proceed(chain.request())
        }
        .build()
    val handler: Handler = App.getHandler()

    /**
     * 发起一个get请求 假如要在地址后面加参数呢？只能手动加了。 retrofit得一分
     * @param suffixUrl 访问地址
     * @param clazz 最终数据的类
     * @param block dsl类
     */
    fun <T> get(suffixUrl: String, clazz: Class<T>, block: KOkCallbackDsl<T>.() -> Unit) {
        var okCallbackDsl = KOkCallbackDsl<T>().also(block)
        val request = Request.Builder()
            .url(App.getBaseUrl() + suffixUrl)
            .header("Authorization", App.getSharedPreferences().getString("token", "")!!)
            .build()
        execute(clazz,request,block)
    }

    /**
     * 发起一个post请求
     * @param suffixUrl 访问地址
     * @param any 一个上传的数据对象
     * @param clazz 最终数据的类
     * @param block dsl类
     */
    fun <T> post(suffixUrl: String,any: Any?, clazz: Class<T>, block: KOkCallbackDsl<T>.() -> Unit){
        val request = Request.Builder()
            .url(App.getBaseUrl() + suffixUrl)
            .header("Authorization", App.getSharedPreferences().getString("token", "")!!)
            .put(any.toRequestBody())
            .build()
        execute(clazz,request,block)
    }

    /**
     * 发起一个post请求
     * @param suffixUrl 访问地址
     * @param paramsMap 一个上传的数据键值对
     * @param clazz 最终数据的类
     * @param block dsl类
     */
    fun <T> post(suffixUrl: String,paramsMap: Map<String,Any>?, clazz: Class<T>, block: KOkCallbackDsl<T>.() -> Unit){
        val request = Request.Builder()
            .url(App.getBaseUrl() + suffixUrl)
            .header("Authorization", App.getSharedPreferences().getString("token", "")!!)
            .put(paramsMap.toRequestBody())
            .build()
        execute(clazz,request,block)
    }

    /**
     * 无论get或者post，都将会调用此方法执行。
     * 虽然方法叫execute，但是是异步
     * 私有方法，你用不了的
     */
    private fun <T> execute(clazz: Class<T>,request: Request,block: KOkCallbackDsl<T>.() -> Unit){
        val okCallbackDsl = KOkCallbackDsl<T>().also(block)
        okHttpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(p0: Call, p1: IOException) {
                handler.post { okCallbackDsl.failure?.invoke("网络异常，请检查网络") }
            }

            override fun onResponse(call: Call, response: Response) {
                val jsonData = response.body()?.string()
                if (response.isSuccessful) {
                    jsonData?.apply {
                        val bean = Gson().fromJson(this, clazz)
                        handler.post { okCallbackDsl.success?.invoke(bean) }
                    }
                } else {
                    handler.post { okCallbackDsl.failure?.invoke("请求异常，请检查程序") }
                }
            }

        })
    }

}